<?php

namespace app\services;

use app\api\validation\Address;
use app\level\LevelFactory;
use app\payment\PayFactory;
use app\traits\Page;
use plugin\admin\app\model\Activity;
use plugin\admin\app\model\Exchange;
use plugin\admin\app\model\ExchangeApply;
use plugin\admin\app\model\OrderShippingNotice;
use plugin\admin\app\model\UserProfile;
use plugin\admin\app\model\UserSearchHistory;
use plugin\admin\app\model\VideoComment;
use plugin\admin\app\model\Goods;
use plugin\admin\app\model\GoodsComment;
use plugin\admin\app\model\GoodsSKU;
use plugin\admin\app\model\Order;
use plugin\admin\app\model\OrderGoods;
use plugin\admin\app\model\OrderRefund;
use plugin\admin\app\model\OrderRefundLog;
use plugin\admin\app\model\OrderReservation;
use plugin\admin\app\model\Reservation;
use plugin\admin\app\model\ShoppingCart;
use plugin\admin\app\model\User;
use plugin\admin\app\model\UserActivity;
use plugin\admin\app\model\UserCoupon;
use plugin\admin\app\model\UserProperty;
use plugin\admin\app\model\UserPropertyLog;
use plugin\admin\app\model\UserUpline;
use SimpleSoftwareIO\QrCode\Generator;
use support\Db;
use support\Express;
use support\Redis;
use Webman\Config;
use Webman\Event\Event;

class OrderService
{
    public static function count()
    {
        $waiting_pay_count = Order::where('status', Order::STATUS_WAITING_PAY)->whereNotNull('cancel_time')->where('user_id', get_user_id())->count();
        $waiting_shipping_count = Order::where('status', Order::STATUS_WAITING_SHIPPING)->whereNotNull('cancel_time')->where('user_id', get_user_id())->count();
        $waiting_receive_count = Order::where('status', Order::STATUS_WAITING_RECEIVE)->whereNotNull('cancel_time')->where('user_id', get_user_id())->count();

        return [
            'waiting_pay_count' => $waiting_pay_count,
            'waiting_shipping_count' => $waiting_shipping_count,
            'waiting_receive_count' => $waiting_receive_count
        ];
    }

    public static function preview($data)
    {
        if (!empty($data['address_id'])) {
            $addressInfo = AddressService::detail($data['address_id']);
        } else {
            $addressInfo = AddressService::getDefault();
        }

        // 非购物车下单,添加到购物车
        if (empty($data['cart_item_ids'])) {
            $data['cart_item_ids'] = [];

            if (empty($data['goods_id'])) {
                throw new \Exception('商品ID不能为空');
            }

            $data['cart_item_ids'][] = ShoppingCartService::add([
                'sku_id' => $data['sku_id'] ?? 0,
                'goods_id' => $data['goods_id'] ?? 0,
                'count' => $data['count'] ?? 1
            ], 1);
        }

        if (ShoppingCartService::isGift($data['cart_item_ids'])) {
            if ($data['count'] != 1) {
                throw new \Exception('报单订单仅限下一件商品');
            }
        }

        $user = User::where('id', get_user_id())->first();

        if (ShoppingCartService::isIntegral($data['cart_item_ids']) && UserService::isLessThanServiceCenter($user['level'])) {
            throw new \Exception('积分商品只允许服务中心或以上等级购买');
        }

        $inviteUserInfo = [];
        if (!empty($data['invite_code'])) {
            $userInfo = User::select(['id'])->where('invite_code', $data['invite_code'])->first();

            if (!$userInfo) {
                throw new \Exception('邀请人不存在');
            }

            $inviteUserInfo = UserProfile::select(['user_id', 'nickname', 'avatar'])->where('user_id', $userInfo['id'])->first()->toArray();
        } else {
            $userInfo = User::select(['id', 'temp_parent_id'])->where('id', get_user_id())->first();

            if (!empty($userInfo['temp_parent_id'])) {
                $inviteUserInfo = UserProfile::select(['user_id', 'nickname', 'avatar'])->where('user_id', $userInfo['temp_parent_id'])->first()->toArray();
            }
        }

        $list = ShoppingCartService::list($data['cart_item_ids']);
        //活动优惠价格
        $activityPreferentialPrice = $list['totalPreferentialPrice'];
        //总商品价格
        $goodsTotalPrice = $list['totalPrice'];
        //邮费
        $shippingFee = $list['totalShippingFee'];

        $couponPreferentialPrice = 0;
        if (!empty($data['coupon_id'])) {
            $coupons = UserCouponService::getOrderCouponList($data['cart_item_ids']);

            foreach ($coupons as $coupon) {
                if ($coupon['id'] == $data['coupon_id'] && $coupon['can_use']) {
                    $couponPreferentialPrice = $coupon['preferential_price'];
                    break;
                }
            }
        }

        //可用积分
        $integralToBalance = ConfigService::get('integral_to_balance');
        $integral = UserPropertyService::getOrderCanUseIntegral($data['cart_item_ids']);

        $integralPrice = 0;
        if (!empty($data['integral'])) {
            if ($data['integral'] > $integral) {
                throw new \Exception('可用积分不足');
            }

            $integralPrice = bcdiv($data['integral'], $integralToBalance, 2);
        }

        //应付金额
        $payPrice = bcadd($goodsTotalPrice, $shippingFee, 2);
        $payPrice = bcsub($payPrice, $couponPreferentialPrice, 2);

        if ($payPrice < $integralPrice) {
            throw new \Exception('积分抵扣额度不能大于总订单金额');
        }

        $payPrice = bcsub($payPrice, $integralPrice, 2);

        return [
            'is_gift_order' => ShoppingCartService::isGift($data['cart_item_ids']),
            'invite_user_info' => $inviteUserInfo,
            'coupon_id' => !empty($data['coupon_id']) ? $data['coupon_id'] : null,
            'goods_list' => $list['list']['valid'],
            'goods_total_market_price' => $list['totalMarketPrice'],
            'goods_total_price' => $goodsTotalPrice,
            'total_recharge_integral' => $list['totalRechargeIntegral'],
            'total_register_integral' => $list['totalRegisterIntegral'],
            'total_integral' => $list['totalIntegral'],
            'shipping_fee' => $shippingFee,     //运费
            'pay_price' => $payPrice,           //应付金额
            'integral_price' => $integralPrice,                             //积分抵扣
            'address_info' => $addressInfo,
            'activity_preferential_price' => $activityPreferentialPrice,    //活动优惠
            'coupon_preferential_price' => $couponPreferentialPrice,        //优惠券优惠
            'cart_item_ids' => $data['cart_item_ids'],
            'can_use_integral' => UserPropertyService::getOrderCanUseIntegral($data['cart_item_ids'])
        ];
    }

    public static function create($data)
    {
        $orderPreviewInfo = self::preview($data);

        if ($orderPreviewInfo['is_gift_order']) {
            $data['pay_way'] = 'rr';
            Event::dispatch('gift-order.before-create', $orderPreviewInfo);
        } else {
            $data['pay_way'] = 'integral';
        }

        if (empty($data['address_id'])) {
            throw new \Exception('请选择地址');
        }
        $addressInfo = AddressService::detail($data['address_id']);

        if (empty($data['pay_way'])) {
            throw new \Exception('请选择支付方式');
        }

        $payWayTypes = PayFactory::create($data['pay_way'])->getSupportPayWayTypes();

        if ($payWayTypes && empty($data['pay_way_type'])) {
            throw new \Exception('支付方式类型不能为空');
        }

        if ($payWayTypes && !in_array($data['pay_way_type'], $payWayTypes)) {
            throw new \Exception('不支持支付方式类型');
        }

        $type = self::getOrderType($orderPreviewInfo);

        $orderNo = self::generateOrderNo();

        $orderInsertData = [
            'invite_user_id' => $orderPreviewInfo['invite_user_info']['user_id'] ?? 0,
            'user_id' => get_user_id(),
            'order_no' => $orderNo,
            'price' => $orderPreviewInfo['pay_price'],
            'integral' => $orderPreviewInfo['integral_price'],
            'goods_price' => $orderPreviewInfo['goods_total_price'],
            'activity_preferential_price' => $orderPreviewInfo['activity_preferential_price'],
            'coupon_preferential_price' => $orderPreviewInfo['coupon_preferential_price'],
            'shipping_fee' => $orderPreviewInfo['shipping_fee'],
            'pay_way' => $data['pay_way'],
            'pay_way_type' => $data['pay_way_type'] ?? null,
            'receive_contact' => $addressInfo['contact_name'],
            'receive_mobile' => $addressInfo['contact_mobile'],
            'receive_address' => $addressInfo['province'] . $addressInfo['city'] . $addressInfo['district'] . $addressInfo['address'],
            'district_id' => $addressInfo['district_id'],
            'city_id' => $addressInfo['city_id'],
            'remark' => $data['remark'] ?? '',
            'status' => Order::STATUS_WAITING_PAY,
            'created_time' => date('Y-m-d H:i:s'),
            'type' => $type,
            'coupon_id' => $orderPreviewInfo['coupon_id'],
        ];

        if (!empty($orderPreviewInfo['coupon_id'])) {
            UserCouponService::check($orderPreviewInfo['coupon_id']);
        }

        if ($orderInsertData['type'] == Order::TYPE_GIFT) {
            $orderInsertData['register_integral'] = $orderPreviewInfo['goods_list'][0]['goods_info']['register_integral'] ?? 0;
            $orderInsertData['recharge_integral'] = $orderPreviewInfo['goods_list'][0]['goods_info']['recharge_integral'] ?? 0;
            $orderInsertData['freeze_integral'] = bcmul($orderPreviewInfo['goods_list'][0]['goods_info']['freeze_integral_rate'] / 100, $orderPreviewInfo['goods_list'][0]['goods_info']['price'], 2);
        }

        Order::insert($orderInsertData);

        $orderGoodsList = [];

        foreach ($orderPreviewInfo['goods_list'] as $goods) {
            if ($orderInsertData['type'] == Order::TYPE_GIFT && !UserService::checkCanBuyThisGift(get_user_id(), $goods['goods_info']['id'])) {
                throw new \Exception('请勿购买不同的报单产品');
            }

            $orderGoodsList[] = [
                'user_id' => get_user_id(),
                'goods_id' => $goods['goods_info']['id'],
                'sku_id' => $goods['goods_info']['sku']['id'] ?? 0,
                'order_no' => $orderNo,
                'goods_name' => $goods['goods_info']['name'],
                'goods_thumb' => $goods['goods_info']['thumb'],
                'sku' => !empty($goods['goods_info']['sku']) ? json_encode($goods['goods_info']['sku'], JSON_UNESCAPED_UNICODE) : null,
                'count' => $goods['count'],
                'price' => !empty($goods['goods_info']['sku']) ? $goods['goods_info']['sku']['price'] : $goods['goods_info']['price'],
                'activity_info' => json_encode($goods['goods_info']['activity'], JSON_UNESCAPED_UNICODE)
            ];
        }

        OrderGoods::insert($orderGoodsList);

        ShoppingCartService::delete(['ids' => $orderPreviewInfo['cart_item_ids']]);

        return $orderNo;
    }

    public static function getOrderType($orderPreviewInfo)
    {
        $type = Order::TYPE_GOODS;
        if ($orderPreviewInfo['is_gift_order']) {
            $type = Order::TYPE_GIFT;
        }

        foreach ($orderPreviewInfo['goods_list'] as $goods) {
            if ($goods['goods_info']['is_normal'] == 1) {
                $type = Order::TYPE_NORMAL;
                break;
            }
        }

        return $type;

    }

    public static function cancel($orderNo, $reason = '')
    {
        $order = Order::where('user_id', get_user_id())->where('order_no', $orderNo)->first();

        if (!$order) {
            throw new \Exception('不存在的订单');
        }

        switch ($order['type']) {
            default:
                if ($order['status'] != Order::STATUS_WAITING_PAY && $order['status'] != Order::STATUS_WAITING_SHIPPING) {
                    throw new \Exception('该订单无法取消');
                }
        }

        if (!empty($reason)) {
            $order->cancel_reason = $reason;
        }

        $order->status = Order::STATUS_CANCEL;
        $order->cancel_time = date('Y-m-d H:i:s');
        $order->save();

        if (!empty($order['coupon_id'])) {
            UserCouponService::back($order['coupon_id']);
        }

        if ($order['pay_time'] && $order['price'] > 0) {
            self::payBack($order);
        }

    }

    public static function delete($orderNo)
    {
        $order = Order::where('user_id', get_user_id())->where('order_no', $orderNo)->first();

        if (!$order) {
            throw new \Exception('不存在的订单');
        }

        if ($order->delete_time) {
            throw new \Exception('不存在的订单');
        }

        $order->delete_time = date('Y-m-d H:i:s');
        $order->save();
    }

    public static function getRangeTimeGiftOrderCount($startTime, $endTime, $userId = null)
    {
        $userId = $userId ?? get_user_id();
        return Order::where('type', Order::TYPE_GIFT)->whereBetween('pay_time', [$startTime, $endTime])->whereNull('cancel_time')->whereNotNull('pay_time')->where('user_id', $userId)->count();
    }

    public static function getRangeTimeChildrenGiftOrderCount($startTime, $endTime, $userId = null)
    {
        $users = User::where('parent_id', $userId)->get()->toArray();
        $userIds = array_column($users, 'id');

        return Order::where('type', Order::TYPE_GIFT)->whereBetween('pay_time', [$startTime, $endTime])->whereNull('cancel_time')->whereNotNull('pay_time')->whereIn('user_id', $userIds)->count();
    }

    public static function list($page, $length, $status, $keyword = '', $type = 0)
    {
        $offset = ($page - 1) * $length;

        $query = Order::select(['order_no', 'status', 'price', 'refund_status', 'refund_type', 'activity_preferential_price', 'coupon_preferential_price', 'created_time', 'register_integral', 'type', 'recharge_integral'])->where('user_id', get_user_id())->whereNull('delete_time');

        if ($status > 0) {
            if ($status != 7) {
                $query = $query->where('status', $status)->where('refund_status', 0);
            } else {
                $query = $query->where('refund_status', '>', 0);
            }
        }

        if ($keyword) {
            if (strpos($keyword, 'NO') !== false) {
                $query = $query->where('order_no', $keyword);
            } else {
                $orderGoodsList = OrderGoods::where('user_id', get_user_id())->where('goods_name', 'like', "%{$keyword}%")->get()->toArray();
                $orderNos = array_column($orderGoodsList, 'order_no');
                if (count($orderNos)) {
                    $query = $query->whereIn('order_no', $orderNos);
                }
            }

            KeywordService::add($keyword, UserSearchHistory::TYPE_ORDER);
        }

        if ($type > 0) {
            $query = $query->where('type', $type);
        }

        $count = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->orderByDesc('id')->get()->toArray();

        $orderNos = array_column($list, 'order_no');
        $orderGoods = OrderGoods::select(['goods_id', 'order_no', 'goods_name', 'goods_thumb', 'count', 'price', 'sku'])->whereIn('order_no', $orderNos)->get()->toArray();

        $comments = GoodsComment::whereIn('order_no', $orderNos)->get()->toArray();
        foreach ($list as $key=>$item) {
            $list[$key]['status_text'] = Order::getStatusText($item);
            foreach ($orderGoods as $goods) {
                if ($goods['order_no'] == $item['order_no']) {
                    $sku = !is_null($goods['sku']) ? json_decode($goods['sku'], true) : [];
                    $goods['sku'] = $sku['sku'] ?? [];
                    $goods['sku_id'] = $sku['id'] ?? 0;

                    $goods['is_comment'] = 0;
                    foreach ($comments as $comment) {
                        if ($comment['goods_id'] == $goods['goods_id'] && $goods['order_no'] == $comment['order_no']) {
                            $goods['is_comment'] = 1;
                            break;
                        }
                    }

                    $list[$key]['goods_list'][] = $goods;
                }
            }

            $list[$key]['refund_type_text'] = OrderRefund::getRefundTypeText($item);

            $list[$key]['rest_pay_time'] = self::getRestPayTime($item);
            $list[$key]['is_gift_order'] = $item['type'] == Order::TYPE_GIFT;
        }

        return Page::wrap($count, $page, $length, $list);
    }

    public static function detail($orderNo)
    {
        $order = Order::select([
            'order_no', 'status', 'price', 'receive_contact', 'receive_mobile', 'receive_address', 'receive_time', 'express_company', 'express_no', 'remark', 'created_time', 'pay_time', 'shipping_time', 'shipping_fee', 'pay_way', 'activity_preferential_price', 'coupon_preferential_price', 'goods_price', 'refund_status', 'refund_type', 'refund_reason', 'register_integral', 'type', 'recharge_integral'])->where('order_no', $orderNo)->where('user_id', get_user_id())->whereNull('delete_time')->first();

        if (!$order) {
            throw new \Exception('订单不存在');
        }

        $order = $order->toArray();

        $orderGoods = OrderGoods::select(['goods_id', 'order_no', 'goods_name', 'goods_thumb', 'count', 'price', 'activity_info', 'sku'])->where('order_no', $orderNo)->get()->toArray();
        $order['status_text'] = Order::getStatusText($order);

        $comments = GoodsComment::where('order_no', $orderNo)->get()->toArray();
        foreach ($orderGoods as $goods) {
            $goods['activity_info'] = json_decode($goods['activity_info'], true);
            $sku = !is_null($goods['sku']) ? json_decode($goods['sku'], true) : [];
            $goods['sku'] = $sku['sku'] ?? [];
            $goods['sku_id'] = $sku['id'] ?? 0;

            $goods['is_comment'] = 0;
            foreach ($comments as $comment) {
                if ($comment['goods_id'] == $goods['goods_id']) {
                    $goods['is_comment'] = 1;
                    break;
                }
            }

            $order['goods_list'][] = $goods;
        }

        $order['refund_type_text'] = OrderRefund::getRefundTypeText($order);
        $order['refund_status_text'] = Order::getRefundStatusText($order['refund_status']);
        $order['pay_way_text'] = UserPropertyLog::getPayWayText($order['pay_way']);
        $order['rest_pay_time'] = self::getRestPayTime($order);
        $order['is_gift_order'] = $order['type'] == Order::TYPE_GIFT;
        $order['total_integral'] = bcadd($order['register_integral'], $order['recharge_integral'], 2);

        return $order;
    }

    public static function goodsList($orderNo)
    {
        $orderGoods = OrderGoods::select(['goods_id', 'order_no', 'goods_name', 'goods_thumb', 'count', 'price', 'activity_info', 'sku'])->where('order_no', $orderNo)->get()->toArray();

        $goodsList = [];
        foreach ($orderGoods as $goods) {
            $sku = !is_null($goods['sku']) ? json_decode($goods['sku'], true) : [];
            $goods['sku'] = $sku['sku'] ?? [];
            $goods['sku_id'] = $sku['id'] ?? 0;

            $goodsList[] = $goods;
        }

        return $goodsList;
    }

    public static function getRestPayTime($order)
    {
        $duration = ConfigService::get('automatic_cancel_order');
        return strtotime($order['created_time']) + $duration * 60;
    }

    public static function expressList($orderNo)
    {
        $order = Order::select(['express_no', 'user_id'])->where('order_no', $orderNo)->first();

        if (!$order) {
            throw new \Exception('不存在的订单');
        }

        if ($order['express_no']) {
            $expressAppCode = ConfigService::get('express_app_code');

            if (empty($expressAppCode)) {
                throw new \Exception('未设置物流服务code, 请在后台->设置->配置中心->商城配置处设置');
            }

            $expressRes = (new Express(getenv('EXPRESS_APPCODE')))->getList($order['express_no']);

            if ($expressRes['status'] == 0) {
                return $expressRes['result'] ?? ['list' => []];
            }
        }

        return ['list' => []];
    }

    public static function refundExpressList($orderNo)
    {
        $order = OrderRefund::where('order_no', $orderNo)->first();

        if (!$order) {
            throw new \Exception('不存在的订单');
        }

        if ($order['refund_express_no']) {
            $expressAppCode = ConfigService::get('express_app_code');

            if (empty($expressAppCode)) {
                throw new \Exception('未设置物流服务code, 请在后台->设置->配置中心->商城配置处设置');
            }

            $expressRes = (new Express(getenv('EXPRESS_APPCODE')))->getList($order['refund_express_no']);

            if ($expressRes['status'] == 0) {
                return $expressRes['result'] ?? ['list' => []];
            }
        }

        return ['list' => []];
    }

    public static function payBack($order)
    {
        PayFactory::create($order['pay_way'])->setData(['user_id' => $order['user_id'], 'order_no' => $order['order_no'], 'total_amount' => $order['price'], 'source' => UserPropertyLog::ORDER_PAY_BACK, 'openid' => UserService::getOpenId($order), 'pay_way_type' => $order['pay_way_type']])->payBack();
    }

    public static function pay($orderNo)
    {
        $tryCount = Redis::get('try_count_' . $orderNo) ?? 0;

        if ($tryCount > 1) {
            Redis::del('try_count_' . $orderNo);
            throw new \Exception('支付失败');
        }

        $order = Order::where('order_no', $orderNo)->where('user_id', get_user_id())->first();

        if ($order['status'] > Order::STATUS_WAITING_PAY) {
            throw new \Exception('该订单已支付');
        }

        if (!$order) {
            throw new \Exception('不存在的订单');
        }

        if ($order['price'] == 0) {
            $payResult = null;
            self::paySuccess($order['order_no']);
        } else {
            $openId = UserService::getOpenId($order);

            $payResult = PayFactory::create($order['pay_way'])->setData(['order_no' => $orderNo, 'total_amount' => $order['price'], 'source' => UserPropertyLog::PAY_ORDER, 'openid' => $openId, 'pay_way_type' => $order['pay_way_type'], 'order' => $order])->pay();

            if (PaymentService::dontNeedCallback($order['pay_way'])) {
                self::paySuccess($orderNo);
            }
        }

        return [$orderNo, $payResult];
    }

    public static function qrcode($orderNo)
    {
        $detail = Order::select([
            'id',
            'check_user_id',
            'check_code',
        ])->where('order_no', $orderNo)->where('user_id', get_user_id())->first();


        if (!$detail) {
            throw new \Exception('不存在的报名活动');
        }

        return (new Generator())->generate($detail['check_code']);
    }

    public static function confirm($data)
    {
        $order = Order::where('order_no', $data['order_no'])->first();

        if (!$order) {
            throw new \Exception('不存在的订单');
        }

        if ($order->user_id != get_user_id() && $order->buyer_user_id != get_user_id()) {
            throw new \Exception('不存在的订单');
        }

        if ($order['status'] != Order::STATUS_WAITING_RECEIVE) {
            throw new \Exception('该订单尚未发货或已收货');
        }

        $order->status = Order::STATUS_WAITING_COMMENT;
        $order->refund_status = 0;
        $order->receive_time = date('Y-m-d H:i:s');
        $order->save();
    }

    public static function checkCode($data)
    {
        $order = Order::where('check_code', $data['check_code'])->where('check_user_id', get_user_id())->first();

        if (!$order) {
            throw new \Exception('不存在的订单');
        }

        if ($order['status'] == Order::STATUS_FINISH) {
            throw new \Exception('该订单已核销');
        }

        $order->status = Order::STATUS_FINISH;
        $order->refund_status = 0;
        $order->receive_time = date('Y-m-d H:i:s');
        $order->save();
    }

    // 普通商品购买成功之后逻辑
    public static function paySuccess($orderNo)
    {
        $order = Order::where('order_no', $orderNo)->first();

        // 修改订单状态
        $order['pay_time'] = date('Y-m-d H:i:s');
        $order['status'] = Order::STATUS_WAITING_SHIPPING;
        $order->save();

        if ($order['type'] == Order::TYPE_GIFT) {
            Event::dispatch('gift-order.after-pay', $order);
        } elseif ($order['type'] == Order::TYPE_GOODS) {
            Event::dispatch('normal-order.after-pay', $order);
        } elseif ($order['type'] == Order::TYPE_ACTIVITY) {
            Event::dispatch('activity-order.after-pay', $order);
        }

        Event::dispatch('order.after-pay', $order);

        if ($order['pay_way'] != PayFactory::BALANCE && $order['balance'] > 0) {
            PropertyService::reduce($order['user_id'], PayFactory::BALANCE, $order['balance'], UserPropertyLog::PAY_ORDER, '', $order['order_no']);
        }
    }

    public static function rebate($order)
    {
        $config = ConfigService::getByGroup('team_reward');

        if (empty($config['team_recommend_rate'])) {
            throw new \Exception('团队奖励直推奖未配置');
        }

        if (empty($config['team_same_rate'])) {
            throw new \Exception('团队奖励平级奖未配置');
        }

        // 返利给上级
        $userInfo = User::where('id', $order['user_id'])->first();

        $upline = UpLineService::get($order['user_id']);

        $i = 1;
        while ($upline) {
            $parentId = array_shift($upline);

            if ($parentId) {
                $parentInfo = User::where('id', $parentId)->first();

                if (UserService::isMoreThanServiceCenter($parentInfo['level'])) {
                    if ($i == 1) {
                        $rate = $config['team_recommend_rate'];
                        $source = UserPropertyLog::INTEGRAL_RECOMMEND_REWARD;
                    } elseif ($i == 2) {
                        $rate = $config['team_same_rate'];
                        $source = UserPropertyLog::INTEGRAL_INDIRECT_RECOMMEND_REWARD;
                    } else {
                        $rate = 0;
                        $source = 0;
                    }

                    $rebateAmount = bcmul($order['price'], $rate / 100, 2);

                    $i++;

                    if ($rebateAmount > 0) {
                        PropertyService::add($parentId, PayFactory::REWARD_INTEGRAL, $rebateAmount, $source, '', $order['order_no']);
                    }
                }
            }

        }

        self::rebateToServiceCenter($order);
    }

    public static function rebateToServiceCenter($order)
    {
        //返利给区县合伙人和城市合伙人
        $unitPrice = ConfigService::get('express_money');

        $count = floor($order['price'] / $unitPrice);

        if ($count < 1) {
            return;
        }

        if ($order['type'] == Order::TYPE_GIFT) {
            $districtReward = ConfigService::get('service_center_reward');
            $cityReward = ConfigService::get('country_partner_reward');
        } elseif ($order['type'] == Order::TYPE_GOODS) {
            $districtReward = ConfigService::get('service_center_integral_reward');
            $cityReward = ConfigService::get('country_partner_integral_reward');
        } else {
            $districtReward = 0;
            $cityReward = 0;
        }

        //4是区县合伙人
        $districtPartners = User::where('level', 4)->where('level_district_id', $order['district_id'])->get()->toArray();
        $rebateAmount = bcmul($districtReward, $count, 2);

        foreach ($districtPartners as $partner) {
            if ($rebateAmount > 0) {
                PropertyService::add($partner['id'], PayFactory::REWARD_INTEGRAL, $rebateAmount, UserPropertyLog::INTEGRAL_DISTRICT_PARTNER_REWARD, '', $order['order_no']);
            }
        }

        //5是城市合伙人
        $cityPartners = User::where('level', 5)->where('level_city_id', $order['city_id'])->get()->toArray();
        $rebateAmount = bcmul($cityReward, $count, 2);

        foreach ($cityPartners as $partner) {
            if ($rebateAmount > 0) {
                PropertyService::add($partner['id'], PayFactory::REWARD_INTEGRAL, $rebateAmount, UserPropertyLog::INTEGRAL_CITY_PARTNER_REWARD, '', $order['order_no']);
            }
        }
    }

    public static function generateOrderNo()
    {
        return 'NO' . substr(str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 11) . mt_rand(1000, 9999);
    }

    public static function generateCheckCode()
    {
        return 'C' . substr(str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 6) . mt_rand(1000, 9999);
    }

    public static function refundList($page, $length, $status)
    {
        $offset = ($page - 1) * $length;
        $query = Order::select(['order_no', 'status', 'price', 'refund_status', 'refund_type', 'refund_desc', 'back_time'])->where('user_id', get_user_id())->where('refund_status', '<>', 0)->whereNull('delete_time');

        if ($status) {
            switch ($status) {
                case 1: //处理中
                    $query = $query->whereIn('refund_status', [1]);
                    break;
                case 2: //已完成
                    $query = $query->whereIn('refund_status', [2, -1, 3, -2]);
                    break;

            }
        }

        $count = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->get()->toArray();

        $orderNos = array_column($list, 'order_no');
        $orderGoods = OrderGoods::select(['order_no', 'goods_name', 'goods_thumb', 'sku', 'count', 'price'])->whereIn('order_no', $orderNos)->get()->toArray();

        foreach ($list as $key=>$item) {
            $list[$key]['status_text'] = Order::getStatusText($item);
            $list[$key]['refund_type_text'] = OrderRefund::getRefundTypeText($item);
            $list[$key]['refund_status_text'] = OrderRefund::getStatusText($item['refund_status']);
            foreach ($orderGoods as $goods) {
                if ($goods['order_no'] == $item['order_no']) {
                    $sku = !is_null($goods['sku']) ? json_decode($goods['sku'], true) : [];
                    $goods['sku'] = $sku['sku'] ?? [];
                    $list[$key]['goods_list'][] = $goods;
                }
            }
        }

        return Page::wrap($count, $page, $length, $list);
    }

    public static function noticeShipping($orderNo)
    {
        $order = Order::where('order_no', $orderNo)->where('user_id', get_user_id())->first();

        if (!$order) {
            throw new \Exception('订单不存在');
        }

        if ($order['status'] == Order::STATUS_WAITING_RECEIVE) {
            throw new \Exception('该订单已发货');
        }

        if (OrderShippingNotice::where('order_no', $orderNo)->where('status', OrderShippingNotice::UN_PROCESS)->count() > 0) {
            throw new \Exception('你已提醒发货');
        }

        OrderShippingNotice::insert([
            'order_no' => $orderNo,
            'created_time' => date('Y-m-d H:i:s'),
            'status' => OrderShippingNotice::UN_PROCESS
        ]);
    }

    public static function refundDetail($data)
    {
        $order = Order::select(['order_no', 'status', 'price', 'refund_status', 'refund_type', 'receive_contact', 'receive_mobile', 'receive_address', 'receive_time', 'express_no', 'express_company', 'refund_desc', 'back_time', 'pay_way'])->where('user_id', get_user_id())->where('order_no', $data['order_no'])->whereNull('delete_time')->first();

        if (!$order) {
            throw new \Exception('该商品没有退款信息');
        }

        $order = $order->toArray();

        $orderRefund = OrderRefund::where('order_no', $order['order_no'])->orderByDesc('created_time')->first();

        if ($orderRefund) {
            $orderRefund = $orderRefund->toArray();
        } else {
            $orderRefund = [];
        }

        $order['refund_reason'] = $orderRefund['refund_reason'] ?? '';
        $order['refund_express_no'] = $orderRefund['refund_express_no'] ?? '';
        $order['refund_express_company'] = $orderRefund['refund_express_company'] ?? '';
        $order['created_time'] = $orderRefund['created_time'] ?? '';
        $order['reject_time'] = $orderRefund['reject_time'] ?? '';
        $order['agree_time'] = $orderRefund['agree_time'] ?? '';

        $config = ConfigService::getByGroup('receive');

        $order['receive_info'] = $config;

        $orderGoods = OrderGoods::select(['order_no', 'goods_name', 'goods_thumb', 'sku', 'count', 'price'])->where('order_no', $order['order_no'])->get()->toArray();
        $order['status_text'] = Order::getStatusText($order);
        $order['refund_type_text'] = OrderRefund::getRefundTypeText($order);
        $order['refund_status_text'] = OrderRefund::getStatusText($order['refund_status']);
        $order['refund_wallet_text'] = OrderRefund::getRefundWalletText($order);
        foreach ($orderGoods as $goods) {
            $sku = !is_null($goods['sku']) ? json_decode($goods['sku'], true) : [];
            $goods['sku'] = $sku['sku'] ?? [];
            $order['goods_list'][] = $goods;
        }


        return $order;
    }

    public static function refundHistory($data)
    {
        $orderRefunds = OrderRefund::where('order_no', $data['order_no'])->orderByDesc('created_time')->get()->toArray();

        $kefuInfo = [
            'nickname' => '系统客服',
            'avatar' => '',
        ];

        $userInfo = UserProfile::select(['nickname', 'avatar'])->where('user_id', $orderRefunds[0]['user_id'])->first();
        $order = Order::where('order_no', $data['order_no'])->first();

        $infos = [];
        foreach ($orderRefunds as $orderRefund) {
            $orderRefundLogs = OrderRefundLog::where('refund_id', $orderRefund['id'])->orderByDesc('created_time')->get()->toArray();

            foreach ($orderRefundLogs as $orderRefundLog) {
                switch ($orderRefundLog['status']) {
                    case OrderRefund::UNPROCESS:
                        $infos[] = [
                            'user_info' => $userInfo,
                            'time' => $orderRefundLog['created_time'],
                            'status' => $orderRefundLog['status'],
                            'status_text' => OrderRefund::getStatusText($orderRefundLog['status']),
                            'list' => [
                                [
                                    'label' => '退款类型',
                                    'value' => OrderRefundService::getRefundTypeText($orderRefund['refund_type'])
                                ],
                                [
                                    'label' => '退款金额',
                                    'value' => $orderRefund['refund_amount']
                                ],
                                [
                                    'label' => '退款原因',
                                    'value' => $orderRefund['refund_reason']
                                ],
                                [
                                    'label' => '退款说明',
                                    'value' => $orderRefund['refund_desc']
                                ],
                            ]
                        ];
                        break;
                    case OrderRefund::AGREE:
                        $infos[] = [
                            'user_info' => $kefuInfo,
                            'time' => $orderRefundLog['created_time'],
                            'status' => $orderRefundLog['status'],
                            'list' => [
                                [
                                    'label' => '退款金额',
                                    'value' => $orderRefund['refund_amount']
                                ],
                                [
                                    'label' => '退款账户',
                                    'value' => Order::getWallet($order['pay_way']),
                                ]
                            ]
                        ];
                        break;
                    case OrderRefund::REJECT:
                        $infos[] = [
                            'user_info' => $kefuInfo,
                            'time' => $orderRefundLog['created_time'],
                            'status' => $orderRefundLog['status'],
                            'list' => [
                                [
                                    'label' => '拒绝原因',
                                    'value' => $orderRefund['reject_reason']
                                ],
                                [
                                    'label' => '拒绝说明',
                                    'value' => $orderRefund['reject_desc']
                                ]
                            ]
                        ];
                        break;
                    case OrderRefund::CANCEL:
                        $infos[] = [
                            'user_info' => $userInfo,
                            'time' => $orderRefundLog['created_time'],
                            'status' => $orderRefundLog['status'],
                            'list' => [
                                [
                                    'label' => '取消原因',
                                    'value' => $orderRefund['cancel_reason']
                                ],
                            ]
                        ];
                        break;
                }
            }
        }

        return $infos;
    }

    public static function autoCancel()
    {
        $config = ConfigService::getByGroup('shop');

        $duration = ConfigService::get('automatic_cancel_order');
        $expiryDatetime = strtotime('-' . $duration . ' minutes');
        $orders = Order::whereNull('pay_time')->whereNull('cancel_time')->where('created_time', '<', date('Y-m-d H:i:s', $expiryDatetime))->get()->toArray();

        foreach ($orders as $order) {
            Db::beginTransaction();
            try {
                Order::where('id', $order['id'])->update(['cancel_time' => date('Y-m-d H:i:s'), 'status' => Order::STATUS_CANCEL]);

                $info = json_decode($order['info'], true);

                ActivityService::unfreeze($order['activity_id'], count($info['personInfos']));

                Db::commit();
            } catch (\Exception $e) {
                Db::rollBack();
            }

        }

    }

    public static function autoReceive()
    {
        $config = ConfigService::getByGroup('shop');

        $duration = $config['automatic_receive_order'] ?? 7;
        $expiryDatetime = strtotime('-' . $duration . ' days');
        $orders = Order::where('status', Order::STATUS_WAITING_RECEIVE)->where('shipping_time', '<', date('Y-m-d H:i:s', $expiryDatetime))->get()->toArray();

        $orderIds = array_column($orders, 'id');

        if ($orderIds) {
            Order::whereIn('id', $orderIds)->update(['receive_time' => date('Y-m-d H:i:s'), 'status' => Order::STATUS_FINISH]);
        }
    }

    public static function totalAmount()
    {
        return Order::whereNotNull('pay_time')->whereNull('cancel_time')->whereNull('delete_time')->sum('price');
    }

    public static function amountSta($startTime, $endTime)
    {
        return Order::whereBetween('pay_time', [$startTime, $endTime])->whereNull('cancel_time')->whereNull('delete_time')->whereNotNull('pay_time')->sum('price');
    }

}